<template>
  <div class="yy-widget-table yy-flex-table_container" :class="{'yy-widget-table--single': options?.isSingleSelect}">
    <el-table
        ref="widgetRef"
        border
        :highlight-current-row="options?.highlight"
        v-loading="isLoading"
        :row-key="typeOf(options?.rowKey) == 'function' ? options?.rowKey() : options?.rowKey"
        :data="data"
        @current-change="handleCurrentChange"
        @select="onSelectOrderRowCheckbox"
        @row-dblclick="onDblClickRow"
        @row-contextmenu="showRowContextmenu"
        @contextmenu.prevent
    >
      <template v-for="column in columns" :key="column.field">
        <el-table-column
                         :show-overflow-tooltip="column.type != 'index'"
                         v-if="column.showable && ((!column.condition && column != false) || column.condition(column))"
                         :type="column.type"
                         :property="column.field"
                         :label="typeOf(column.label) == 'function' ? column.label() : column.label"
                         :width="column.width"
                         :min-width="column.minWidth || 120"
                         :align="column.align"
                         :fixed="column.fixed || false"
                         :sortable="column.sortable"
        >
          <template #default="scope" v-if="formats">
            <template v-if="formats[column.field]">
              <template v-if="formats[column.field].slot">
                <slot :name="formats[column.field].slot" :row="scope.row" :column="column"></slot>
              </template>
              <template v-if="column.field == 'action'">
                <template v-for="action of formats[column.field].items" :key="action.value">
                  <span v-if="!action.hide && (!action.condition || (action.condition && action.condition(scope.row)))">
                    <span v-if="action.elType === 'button'">
                      <el-button size="small" v-if="!action.confirm" :underline="false"
                               class="yy-widget-table_action-item"
                               :type="action.type || 'primary'"
                               :color="action.color || ''"
                               :disabled="(action.disabled && typeOf(action.disabled) === 'function') ? action.disabled(scope.row, action) : action.disabled"
                               @click.stop="action.atClick(scope.row, action)">
                        <span>{{action.label}}</span>
                      </el-button>
                      <el-popconfirm v-else :title="action.confirm.title" @confirm="action.confirm.atConfirm(scope.row, action)">
                        <template #reference>
                          <el-button size="small" :underline="false" :type="action.type || 'danger'"
                                   :color="action.color || ''"
                                   class="yy-widget-table_action-item"
                                   :disabled="(action.disabled && typeOf(action.disabled) === 'function') ? action.disabled(scope.row, action) : action.disabled"
                          >
                            <span>{{action.label}}</span>
                          </el-button>
                        </template>
                      </el-popconfirm>
                    </span>
                    <template v-else>
                      <el-link v-if="!action.confirm" :underline="false"
                               class="yy-widget-table_action-item"
                               :type="action.type || 'primary'"
                               :disabled="(action.disabled && typeOf(action.disabled) === 'function') ? action.disabled(scope.row, action) : action.disabled"
                               @click.stop="action.atClick(scope.row, action)">
                        <span>{{action.label}}</span>
                      </el-link>
                      <el-popconfirm v-else :title="action.confirm.title" @confirm="action.confirm.atConfirm(scope.row, action)">
                        <template #reference>
                          <el-link :underline="false" :type="action.type || 'danger'"
                                   class="yy-widget-table_action-item"
                                   :disabled="(action.disabled && typeOf(action.disabled) === 'function') ? action.disabled(scope.row, action) : action.disabled"
                          >
                            <span>{{action.label}}</span>
                          </el-link>
                        </template>
                      </el-popconfirm>
                    </template>
                  </span>
                </template>
              </template>
              <span v-else-if="formats[column.field].labelFormat">
                <el-text v-if="formats[column.field].textType == 'text'" :type="formats[column.field].typeFormat ? formats[column.field].typeFormat(scope.row[column.field], scope.row): 'primary'">
                  {{formats[column.field].labelFormat(scope.row[column.field], scope.row)}}
                </el-text>
                <el-link v-else-if="formats[column.field].textType == 'link'" :underline="false" :type="formats[column.field].typeFormat ? formats[column.field].typeFormat(scope.row[column.field],scope.row): 'primary'">
                  {{formats[column.field].labelFormat(scope.row[column.field], scope.row)}}
                </el-link>
                <el-tag v-else-if="formats[column.field].textType == 'tag'" :type="formats[column.field].typeFormat ? formats[column.field].typeFormat(scope.row[column.field], scope.row): 'primary'">
                  {{formats[column.field].labelFormat(scope.row[column.field], scope.row)}}
                </el-tag>
                <span v-else v-html="formats[column.field].labelFormat(scope.row[column.field], scope.row)"></span>
              </span>
            </template>
          </template>
        </el-table-column>
      </template>
    </el-table>
    <div class="yy-page-paging" v-if="usePaging">
      <el-pagination small background layout="prev, pager, next, total" :total="paging.total"
                     v-model:current-page="paging.pageIndex"
                     v-model:page-size="paging.pageSize"
                     @current-change="paging.pageChange"
      />
    </div>

    <teleport to="body">
      <el-menu
          class="el-table-contextmenu"
          v-click-outside= "hideRowContextMenu"
          :default-active="1"
          mode="vertical"
          v-if="contextMenuData.show"
          @close="hideRowContextMenu"
          :style="{ left: contextMenuData.left + 'px', top: contextMenuData.top + 'px' }"
      >
        <div class="el-menu-header" v-if="contextMenu && contextMenu.title">{{typeOf(contextMenu.title) === 'function' ? contextMenu.title(contextMenuData.selectedRow, contextMenuData.selectedColumn) : contextMenu.title}}</div>
        <template v-for="(menu, index) in contextMenuList()">
          <el-menu-item :index="menu.key"
                        :disabled="menu.condition && (typeOf(menu.condition) === 'function' ? !menu.condition(contextMenuData.selectedRow) : !menu.condition)"
                        @click="onRowContextMenu(contextMenuData.selectedRow, menu)"
          >{{menu.label}}</el-menu-item>
        </template>
      </el-menu>
    </teleport>
  </div>
</template>
<script setup lang="ts">
import {
  ref,
  watch,
  defineEmits,
  defineProps,
  nextTick,
  onMounted,
  onUpdated,
  onBeforeMount,
  onBeforeUnmount,
  reactive, computed
} from 'vue'
  import {typeOf} from "../../utils/yayi";
  import { ClickOutside as vClickOutside } from 'element-plus'


  const $emit = defineEmits({
    currentChange: (current) => current,
    dblClickRow: (data) => data
  })

  const contextMenuData = reactive({
    show: false,
    left: 0,
    top: 0,
    selectedRow: null,
    selectedColumn: null
  })
  const contextMenuList = computed(() => {
     return () => {
       const data = props.contextMenu && props.contextMenu.data
           ? typeOf(props.contextMenu.data) === 'function'
               ? props.contextMenu.data(contextMenuData.selectedRow, contextMenuData.selectedColumn)
               : props.contextMenu.data
           : []
       return data
     }
  })

  const props = defineProps({
    selectedRow: {
      type: Object,
      required: false,
      default: null
    },
    columns: {
      type: Array,
      required: true,
      default: () => null
    },
    data: {
      type: Array,
      required: false,
      default: () => []
    },
    formats: {
      type: Object,
      required: false,
      default: () => null
    },
    contextMenu: {
      type: Object,
      required: false,
      default: () => null
    },
    options: {
      type: Object,
      required: false,
      default: () => null
    },
    pagingData: {
      type: Object,
      required: false,
      default: () => null
    },
    isLoading: {
      type: Boolean,
      required: false,
      default: false
    }
  })
  const widgetRef = ref()
  const usePaging = ref(false)

  const paging = ref({total: 0, pageIndex: 1, pageSize: 50, pageChange: (pageIndex) => pageIndex})

  onBeforeMount(() => {
    window.addEventListener('resize', onWindowResize)
  })

  const onWindowResize = () => {
    clearAuthHeight()
    nextTick(() => {
      resetAutoHeight()
    })
  }

  const handleCurrentChange = (current) => {
    if (props.options?.highlight && current) {
      $emit('currentChange', current)
      onSelectOrderRowCheckbox(null, current)
    }
  }

  const onSelectOrderRowCheckbox = (selection, row) => {
    if(selection && row) {
      if(props.options?.isSingleSelect) {
        const selects = widgetRef.value.getSelectionRows()
        selects.forEach(item => {
          widgetRef.value.toggleRowSelection(item, false)
        })
        widgetRef.value.toggleRowSelection(row, true)
      }
    }
  }

const onDblClickRow = (row) => {
  $emit('dblClickRow', row)
}


  function showRowContextmenu(row,column,event)
  {
    contextMenuData.selectedRow = row
    contextMenuData.selectedColumn = column
    if (contextMenuList.value()?.length) {
      contextMenuData.show = true;
      contextMenuData.left = event.clientX+1;
      contextMenuData.top = event.clientY+1;
    }
    event.preventDefault();
  }


  function hideRowContextMenu()
  {
    contextMenuData.show = false;
  }

  function onRowContextMenu(row, menu){
    menu.atClick(row)
    contextMenuData.show = false;
  }


  const clearAuthHeight = () => {
    const wRef = widgetRef.value
    if (wRef) {
      const el = wRef.$el
      const innerWrapper = el.querySelector('div.el-table__inner-wrapper')
      el.removeAttribute("style")
      innerWrapper.removeAttribute("style")
    }
  }

  const resetAutoHeight = () => {
    const wRef = widgetRef.value
    if (wRef) {
     const el = wRef.$el
     const innerWrapper = el.querySelector('div.el-table__inner-wrapper')
     const tableRenderedHeight = el.getBoundingClientRect().height
     el.style.height = (tableRenderedHeight + 1) + 'px'
     innerWrapper.style.height =  (tableRenderedHeight + 1) + 'px'
   }
  }

  onBeforeUnmount(() => {
    window.removeEventListener('resize', onWindowResize, true);
  })

  watch(() => props.pagingData, () => {
    if (props.pagingData) {
      usePaging.value = props.pagingData.isPaging
      paging.value = {
        total: props.pagingData.total,
        pageSize: props.pagingData.pageSize,
        pageIndex: props.pagingData.pageIndex,
        pageChange: props.pagingData.pageChange
      }
    }
  }, {immediate: true})

  watch(() => props.data, () => {
    clearAuthHeight()
    if (props.data?.length && props.selectedRow) {
      const index = props.data.findIndex((item:any) => item.id === props.selectedRow.id)
      if (index >= 0) {
        widgetRef.value.setCurrentRow(props.selectedRow)
        nextTick(() => {
          widgetRef.value.toggleRowSelection(props.selectedRow, true)
        })
      }
    }
    //console.log('-----------------table watch data change--------------------', props.data)
    setTimeout(() => {
      resetAutoHeight()
    }, 2000)
  }, {immediate: true, deep: true})

  watch(() => props.selectedRow, () => {
    if (props.selectedRow) {
      widgetRef.value.setCurrentRow(props.selectedRow)
      nextTick(() => {
        widgetRef.value.toggleRowSelection(props.selectedRow, true)
      })
    }
  })

  defineExpose({
    onWindowResize
  })
</script>
<style lang="scss">
  .el-table-contextmenu {
    position: absolute;
    left: 0;
    top: 0;
    background: #fff;
    box-shadow: 0px 0px 12px 0px #cccccc;
    border: 1px solid #ddd;
    z-index: 9999;
    width: auto !important;
    font-size: 16px;
    min-width: 150px;
    display: flex;
    flex-direction: column;
    align-items: center;
    .el-menu-header {
      width: 100%;
      padding: 10px 15px;
      background: #f1f1f1;
    }
    .el-menu-item {
      height: 32px;
      margin: 3px 0;
      padding: 3px 15px;
      width: 100%;
    }
  }
</style>
<style scoped lang="scss">
  .yy-widget-table {
    &--single {
      :deep(.el-table__row) {
        cursor: pointer;
      }
      :deep(.el-table__header th:first-child .el-checkbox) {
        display: none;
      }
      :deep(.el-table-column--selection .cell) {
        padding: 0 5px;
      }
      :deep(.el-table__row.current-row) {
        position: relative;
        td:first-child{
          &:before {
            content: '';
            position: absolute;
            left: 0;
            top: 0;
            bottom: 0;
            border-left: 5px solid #1d90fd;
          }
        }
      }
    }
    &_action-item {
      margin: 0 5px;
    }
  }
</style>
